/**

 * @author admin

 * 2014年8月12日

 */

package com.tmall.testgen.client.config;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.springframework.core.io.UrlResource;

import com.tmall.testgen.common.util.StringUtil;

public class ConfigUtil {
	
	
	public static void addJarToProjectConfig(String projectName,String rootPath,List<String> jars) throws Exception{
		IJavaProject javaProject = getJavaProject(projectName);
		IClasspathEntry[]  old=javaProject.getRawClasspath();
		
		
		Set<String> oldSet=new HashSet<String>();
		for(int i=0;i<old.length;i++){
			oldSet.add(old[i].getPath().toString());
		}
		
		List<IClasspathEntry > tem=new ArrayList<IClasspathEntry >();
		for(int j=0;j<jars.size();j++){
			String p=rootPath+"/"+jars.get(j);
			p=p.replaceAll("\\\\", "/");
			if(oldSet.contains(p))
				continue;
			
			tem.add(JavaCore.newLibraryEntry(new Path(rootPath+"/"+jars.get(j)), null, null));
		}
		if(tem.size()==0)
			return;
		
		IClasspathEntry[] newE=new  IClasspathEntry[old.length+tem.size()];
		
		int i=0;
		for(;i<old.length;i++){
			newE[i]=old[i];
		}
		
		for(int j=0;j<tem.size();j++){
			String p=rootPath+"/"+jars.get(j);
			p=p.replaceAll("\\\\", "/");
			newE[i] = tem.get(j);
			i++;
		}
		
		
		javaProject.setRawClasspath(newE, null);
	}
	public static URLClassLoader getClassLoader(String projectName) throws Exception{
		return ConfigUtil.getClassLoader(projectName, ConfigUtil.class.getClassLoader());
	}
	
	private static List<String> getClassPath(String workSpaceLocation,String projectName,IJavaProject javaProject,IClasspathEntry[] classpathEntries) throws Exception{
	    
	    List<String> result=new ArrayList<String>();
	    if(classpathEntries==null)
	        return result;
	    
	    for(IClasspathEntry i:classpathEntries){
            String location=i.getPath().toString();
            if(i.getEntryKind()==IClasspathEntry.CPE_LIBRARY){
                if(location.startsWith("/"+projectName))
                    location=location.replaceFirst("/"+projectName, "");
                
                if(location.startsWith("/")){
                    result.add(workSpaceLocation+location);
                }else{
                    result.add(location);
                }
            }else if(i.getEntryKind()==IClasspathEntry.CPE_VARIABLE){
                int pos=location.indexOf("/");
                String var=location.substring(0,pos);
                result.add(getVarPath(var)+location.substring(pos));
            }
            else if(i.getEntryKind()==IClasspathEntry.CPE_CONTAINER&&!i.getPath().toString().contains("JRE_CONTAINER")){
                
                IClasspathEntry[] entries=JavaCore.getClasspathContainer(i.getPath(), javaProject).getClasspathEntries();
                result.addAll(getClassPath(workSpaceLocation,projectName,javaProject,entries));
            }
        }
	    return result;
	}
	
	/**
	 * 仿制指定工程的类加载器
	 * @param targetProjectPath
	 * @param parent
	 * @return
	 * @throws Exception 
	 */
	public static  URLClassLoader getClassLoader(String projectName,ClassLoader parent) throws Exception{
		List<String> refProjectOutPuts=getRefProjectOutputs(projectName,true);
		
		IJavaProject javaProject = getJavaProject(projectName);
		IClasspathEntry[] classpathEntries = javaProject.getRawClasspath();
		
		List<String> result=new ArrayList<String>();
		if(refProjectOutPuts!=null){
			for(String ref:refProjectOutPuts){
				result.add(ref+"/");
			}
		}
		
		if(classpathEntries==null)
			return null;
		
		String workSpaceLocation=getWorkSpaceLocation(projectName);
		result.addAll(getClassPath(workSpaceLocation,projectName,javaProject,classpathEntries));
		
		
		URL[] urls=new URL[result.size()];
		for(int i=0;i<result.size();i++){
			urls[i]=new UrlResource("file", result.get(i)).getURL();
		}
		return new URLClassLoader(urls,parent);
	} 
	/**
	 * 获取指定工程的依赖工程（递归）
	 * @param projectName
	 * @return
	 * @throws Exception
	 */
	public static List<String> getRefProjectNames(String projectName)throws Exception{
		
		IJavaProject javaProject = getJavaProject(projectName);
		
		
		List<String> projectNames=Arrays.asList(javaProject.getRequiredProjectNames());
		
		if(projectNames==null||projectNames.size()==0)
		    return new ArrayList();
		
		Set<String> resultSet=new HashSet<String>();
		resultSet.addAll(projectNames);
		
		for(String name:projectNames){
		    resultSet.addAll(getRefProjectNames(name));
		}
		
		List<String> result=new ArrayList<String>();
		
		for(String tem:resultSet){
		    result.add(tem);
		}
		return result;
	}
	
	
	/**
	 * 获取所有依赖工程的output
	 * @param projectName
	 * @return
	 * @throws Exception 
	 */
	public static List<String> getRefProjectOutputs(String projectName,boolean containItself) throws Exception{
		List<String> refProjectNames=getRefProjectNames(projectName);
		List<String> result=new ArrayList<String>();
		if(containItself)
			result.add(getOutPutByProjectName(projectName));
		
		if(refProjectNames==null)
			return result;
		
		for(String ref:refProjectNames){
			result.add(getOutPutByProjectName(ref));
		}
		return result;
	}
	
	/**
	 * 获取指定工程的outPut,到工程 根目录
	 * @param targetProjectPath
	 * @return
	 * @throws Exception 
	 */
	public static String getOutPutByProjectName(String projectName) throws Exception{
		IJavaProject javaProject = getJavaProject(projectName);
		return javaProject.getProject().getLocation()+""+javaProject.getOutputLocation().toString().replaceAll("/"+projectName, "");
	}
	
	private static IJavaProject getJavaProject(String projectName){
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IProject project = workspace.getRoot().getProject(projectName);
		return JavaCore.create(project);
	}
	/**
	 * 获取指定工程 所在的工作空间目录，不包含结束符
	 * @param projectName
	 * @return
	 */
	private static String getWorkSpaceLocation(String projectName){
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IProject project = workspace.getRoot().getProject(projectName);
		String location=project.getLocation().toString();
		if(location.endsWith("/"))
		    return location.substring(0, location.lastIndexOf("/"));
		return location;
	}
	/**
	 * 获取指定工程的所有src相对路径
	 * @return
	 */
	public static List<String> getProjectSrcs(String projectName)throws Exception{
		IJavaProject javaProject = getJavaProject(projectName);
		IClasspathEntry[] classpathEntries = javaProject.getRawClasspath();
		
		List<String> result=new ArrayList<String>();
		if(classpathEntries==null)
			return result;
		
		
		for(IClasspathEntry i:classpathEntries){
			if(i.getEntryKind()==IClasspathEntry.CPE_SOURCE){
				result.add(i.getPath().toString());
			}
		}
		return result;
	}
	
	
	
	/**
	 * 寻找eclipse中定义的变量所对应的值
	 * @param var
	 * @return
	 */
	public static  String getVarPath(String var) {
		IEclipsePreferences pref = new InstanceScope().getNode(JavaCore.PLUGIN_ID);
		return pref.get("org.eclipse.jdt.core.classpathVariable."+var, "");
	}
	
	
	
	
}
